import 'dart:collection';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/utils/toast_utils.dart';
import 'package:flutter_app/values/MyColors.dart';
import 'package:flutter_screenutil/src/size_extension.dart';
import 'package:table_calendar/table_calendar.dart';

import 'package:flutter_app/r.dart';
/**
 * @Description: 使用 table_calendar  自定义日历组件
 * @Author: 下雨了
 * @CreateDate: 2021-11-1 16:31:28
 * @UpdateUser: 下雨了
 * @UpdateDate:  2021年11月23日15:46:12
 * @UpdateRemark: 使用 ignorePointer 组件代替  isClick属性
 * @UpdateDate:  2021-11-24 10:51:04
 * @UpdateRemark: 新增 回调 所有已选日期回调， 删除 启用新增日期回调
 *                只保留 接口和参数，其他方法已删除，请参考 {@link  test/deprecated/CustomCalendar.dart}
 * @Version: 1.2
 */

/// 自定义回调   新增日期回调
@deprecated
typedef OnAddDateTimeCallback = void Function(List<String> addDateTime);

/// 自定义回调  用户操作后，所有已选的日期
typedef OnDateTimeCallback = void Function(List<String> checkedTime);

class CustomCalendar extends StatefulWidget {
  final DateTime focusedDay;
  final DateTime firstDay;
  final DateTime lastDay;
  final List<DateTime>? disabledDays; // 被禁止的日期
  final List<DateTime>? selectedDays; // 已经选择的日期
  final List<DateTime>? holidayDays; // 假期日期

  // absorbPointer开启absorbing：本身可以接收点击事件，但不会把事件传递给子组件。
  // ignorePointer开启ignoring：本身和子组件都不能接收点击事件。
  @deprecated
  final bool isClick; // 没有禁止的日期 能否点击  true能点击（默认）  false不能点击

  @deprecated
  final OnAddDateTimeCallback? onAddDateTimeCallback;

  final OnDateTimeCallback onDateTimeCallback;

  const CustomCalendar({
    Key? key,
    required this.focusedDay, // 当前天数
    required this.firstDay, // 第一天
    required this.lastDay, // 最后一天
    this.disabledDays, // 禁用的天数 Set
    this.selectedDays,  // 已选的天数
    this.holidayDays,  // 已选的天数
    required this.onDateTimeCallback, // 新增 用户操作后，所有已选的日期


    @deprecated
    this.isClick = true,
    @deprecated
    this.onAddDateTimeCallback, // 新增日期回调

  }) : super(key: key);

  @override
  CustomCalendarState createState() => CustomCalendarState();
}

class CustomCalendarState extends State<CustomCalendar> {
  // 通知事件
  // final ValueNotifier<List<Event>> _selectedEvents = ValueNotifier([]);

  // 假期的日期 使用 a `LinkedHashSet` 检查两个DateTime对象是否在同一天。
  final Set<DateTime> _holidayDays = LinkedHashSet<DateTime>(
    equals: isSameDay,
    hashCode: getHashCode,
  );

  // 已选中的日期 使用 a `LinkedHashSet` 检查两个DateTime对象是否在同一天。
  final Set<DateTime> _selectedDays = LinkedHashSet<DateTime>(
    equals: isSameDay,
    hashCode: getHashCode,
  );

  // 禁用的日期 使用 a `LinkedHashSet` 检查两个DateTime对象是否在同一天。
  final Set<DateTime> _disabledDays = LinkedHashSet<DateTime>(
    equals: isSameDay,
    hashCode: getHashCode,
  );

  CalendarFormat _calendarFormat = CalendarFormat.month;

  late DateTime _selectedDay = widget.focusedDay;
  late DateTime _focusedDay = widget.focusedDay;

  /// 设置假期日期
  void _setHolidayDays(List<DateTime> data) {
      data.forEach((element) {
        _holidayDays.add(element);
      });
  }

  /// 设置禁止日期
  void _setDisabledDays(List<DateTime> data){
    data.forEach((element) {
      _disabledDays.add(element);
    });
  }

  // 设置已选择日期 和 已选择日期的 初始值
  /// 设置已选择日期
  void _setSelectedDays(List<DateTime> data){
    data.forEach((element) {
      _selectedDays.add(element);
    });
  }

  // 更新 新增加 和 已选择 的日期
  /// 更新 已选择 的日期
  void _upSelectedDays(DateTime data) {
    if (_selectedDays.contains(data)) {
      _selectedDays.remove(data);
    } else {
      if (_selectedDays.length > 1) {
        toast.show("最多选择2天");
        return;
      }
      _selectedDays.add(data);
    }
    List<String> list = [];
    _selectedDays.forEach((element) {
      list.add(element.year.toString() + "-" + element.month.toString() + "-" + element.day.toString());
    });
    widget.onDateTimeCallback.call(list);
  }

  /// 主widget 使用GlobalKey 来调用 子widget的方法
  /// 用来更新 选中日期的 添加和删除
  /// 更新数据
  upDateSelectedDays(String data){
    DateTime dataTime =  DateTime.parse(data);
    if (_selectedDays.contains(dataTime)) {
      _selectedDays.remove(dataTime);
    }  else {
      _selectedDays.add(dataTime);
    }
  }

  @override
  void initState() {
    super.initState();
    if (widget.selectedDays != null) {
      _setSelectedDays(widget.selectedDays!);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 24.r),
      child: TableCalendar(
        locale: "zh_CN",
        focusedDay: widget.focusedDay,
        firstDay: widget.firstDay,
        lastDay: widget.lastDay,
        // 显示头部
        headerVisible: false,
        // 显示 周
        daysOfWeekVisible: true,
        daysOfWeekHeight: 20.r,
        daysOfWeekStyle: DaysOfWeekStyle(
          weekdayStyle: TextStyle(color: MyColors.FF777777, fontSize: 13.sp),
          weekendStyle: TextStyle(color: MyColors.FF777777, fontSize: 13.sp),
        ),
        // 设置 table的 行高
        rowHeight: 50.r,
        // 设置日历周开始时间 这里设置为周一为每周的开始时间
        startingDayOfWeek: StartingDayOfWeek.sunday,
        // 设置选中状态和非选中状态颜色等参数
        calendarStyle: CalendarStyle(
          cellPadding: EdgeInsets.only(bottom: 12.r),
          // 假期
          holidayTextStyle: TextStyle(color: MyColors.FF2763B9, fontSize: 14.sp),
          holidayDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(2.r),
            color: MyColors.FFA7D4F8,
            // image: DecorationImage(image: ExactAssetImage(R.assetsImgIcon84), fit: BoxFit.cover)
          ),
          // 确定与当前聚焦月份不匹配的天单元格是否可见
          outsideDaysVisible: false,
          // 当前日期
          todayTextStyle: TextStyle(color: MyColors.FF2763B9, fontSize: 14.sp),
          // 对匹配当前日期的day单元格 进行装饰。
          todayDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(2.r),
            color: MyColors.FFDFEFFC,
          ),
          // 选择
          selectedTextStyle: TextStyle(color: Colors.white, fontSize: 14.sp),
          selectedDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(2.r),
            color: MyColors.FFF03F35,
            image: DecorationImage(image: ExactAssetImage(R.assetsImgIcon55), fit: BoxFit.cover)
          ),
          // 禁用
          disabledTextStyle: TextStyle(color: MyColors.FF999999, fontSize: 14.sp),
          disabledDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(2.r),
            color: MyColors.FFEBEBEB,
          ),
          // 周末
          weekendTextStyle: TextStyle(color: MyColors.FF2763B9, fontSize: 14.sp),
          weekendDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(2.r),
            color: MyColors.FFDFEFFC,
          ),
          // 默认
          defaultTextStyle: TextStyle(color: MyColors.FF2763B9, fontSize: 14.sp,),
          defaultDecoration: BoxDecoration(
            borderRadius: BorderRadius.circular(2.r),
            color: MyColors.FFDFEFFC,
          ),
        ),
        // 点击禁用的日期
        onDisabledDayTapped: (DateTime disabledDay){
          print("onDisabledDayTapped = " + disabledDay.toString());
          // setState(() {
          //   if (_disabledDays.contains(disabledDay)) {
          //     _disabledDays.remove(disabledDay);
          //   } else {
          //     _disabledDays.add(disabledDay);
          //   }
          // });
        },
        // 假期 此处拿来做特殊标记
        holidayPredicate: (DateTime day) {
          if (widget.holidayDays != null) {
            _setHolidayDays(widget.holidayDays!);
            if (_holidayDays.contains(day) ) {
              return true;
            } else {
              return false;
            }
          } else {
            return false;
          }
        },
        // 是否应该启用给定的日期  返回' false '，这一天将被禁用。
        enabledDayPredicate: (DateTime day) {
          if (widget.disabledDays != null) {
            _setDisabledDays(widget.disabledDays!);
            if (_disabledDays.contains(day) ) {
              return false;
            } else {
              return true;
            }
          } else {
            return true;
          }
        },
        // 决定是否将给定的日期标记为选定的日期
        selectedDayPredicate: (DateTime day) {
          //print("selectedDayPredicate = " + day.toString());

          return _selectedDays.contains(day);
          // return isSameDay(_selectedDay, day);
        },
        // 包含选定的日期和聚焦的日期。
        onDaySelected: (DateTime selectedDay, DateTime focusedDay){
          print("onDaySelected = " + selectedDay.toString());
          setState(() {
            _focusedDay = focusedDay;
            // Update values in a Set
            if (widget.isClick) {
              _upSelectedDays(selectedDay);
            }
          });
        },
        // 当前可见的 日历页 被更改时调用。
        onPageChanged: (DateTime focusedDay){
          _focusedDay = focusedDay;
        },
        // 当期 日历格式 被更改时调用。
        onFormatChanged: (format) {
          if (_calendarFormat != format) {
            // Call `setState()` when updating calendar format
            setState(() {
              _calendarFormat = format;
            });
          }
        },
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
  }
}

int getHashCode(DateTime key) {
  return key.day * 1000000 + key.month * 10000 + key.year;
}
